package ysy.ioc.util;

import android.app.Activity;
import android.os.Build;
import android.view.View;

import androidx.annotation.RequiresApi;

import com.example.mytest.R;

import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

import ysy.ioc.annotation.BindView;
import ysy.ioc.annotation.ClickAnnotation;
import ysy.ioc.annotation.ContentView;
import ysy.ioc.annotation.ViewClick;

public class InjectUtils {

    @RequiresApi(api = Build.VERSION_CODES.N)
    public static void inject(Activity activity) {
        injectContentView(activity);
        injectBindView(activity);
        injectClickView(activity);
    }

    @RequiresApi(api = Build.VERSION_CODES.N)
    private static void injectClickView(Activity activity) {
        Class<? extends Activity> aClass = activity.getClass();
        Method[] declaredMethods = aClass.getDeclaredMethods();
        for (Method declaredMethod : declaredMethods) {
            ViewClick annotation = declaredMethod.getAnnotation(ViewClick.class);
            if (annotation == null) continue;
            int[] value = annotation.value();//id
            Class<? extends Annotation> annotationTypeClass = annotation.annotationType();
            ClickAnnotation clickAnnotation = annotationTypeClass.getAnnotation(ClickAnnotation.class);
            if (clickAnnotation==null) continue;

            String annotationCallback = clickAnnotation.annotationCallback();
            Class annotationClass = clickAnnotation.annotationClass();
            String annotationMonth = clickAnnotation.annotationMonth();

            for (int i : value) {
                View view = activity.findViewById(i);
                try {
                    Method viewMethod = View.class.getDeclaredMethod(annotationMonth, annotationClass);
                    viewMethod.setAccessible(true);
                    Object o = Proxy.newProxyInstance(view.getClass().getClassLoader(), new Class[]{annotationClass}, new InvocationHandler() {
                        @Override
                        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                            if (method.getName().equals(annotationCallback)){
                                declaredMethod.invoke(activity,args);
                            }
                            return null;
                        }
                    });

                    if (o!=null){
                        viewMethod.invoke(view,o);
                    }

                } catch (NoSuchMethodException e) {
                    e.printStackTrace();
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                } catch (InvocationTargetException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    private static void injectBindView(Activity activity) {
        Class<? extends Activity> aClass = activity.getClass();
        Field[] declaredFields = aClass.getDeclaredFields();
        for (Field declaredField : declaredFields) {
            BindView annotation = declaredField.getAnnotation(BindView.class);
            if (annotation == null) {
                continue;
            }
            int value = annotation.value();
            View viewById = activity.findViewById(value);
            if (!declaredField.isAccessible()) {
                declaredField.setAccessible(true);
            }
            try {
                declaredField.set(activity, viewById);
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }
        }
    }

    private static void injectContentView(Activity activity) {
        Class<? extends Activity> aClass = activity.getClass();
        ContentView annotation = aClass.getAnnotation(ContentView.class);
        if (annotation==null) return;
        int value = annotation.value();
        if (value > 0) {
            activity.setContentView(value);
        }
    }
}
